package main

import (
	"go-scripts/services"
	"go-scripts/common"
	"runtime"
	"golang.org/x/net/websocket"
	"gopkg.in/mgo.v2/bson"
	"fmt"
	"os"
	"encoding/json"
	"time"
	"bufio"
	"go-scripts/config"
	"net/http"
	"net/url"
	"strings"
	"strconv"
)

//初始化全局变量
var redisService *services.RedisService = services.GetRedisService()
var logger *common.Log = common.GetLogger()
var serverUrl = config.GetConfig().GetNodeServerUrl()

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	defer func() {
		if err := recover(); err != nil {
			logger.Error(err.(string))
		}
	}()
	stocks, err := redisService.GetStocks()
	token, err := common.GetToken()
	url := "ws://gw.yundzh.com/ws?token=" + token
	origin := "http://gw.yundzh.com"
	//建立websocket连接
	ws, err := websocket.Dial(url, "", origin)
	//60秒ping一次，防止断开
	go func(ws *websocket.Conn) {
		for {
			time.Sleep(60 * time.Second)
			ping(ws)
			logger.Info("发送ping")
		}
	}(ws)
	if err != nil {
		panic(err.Error())
	}
	//打开时订阅消息
	logger.Info("socket open")
	stkOnOpen(stocks, ws)
	for {
		var res string
		err := websocket.Message.Receive(ws, &res)
		if err != nil {
			fmt.Println("websocket disconnected")
			os.Exit(0)
		}
		//接受并处理消息
		stkOnMessage(res)
	}
}
//websocket打开
func stkOnOpen(stocks []string, ws *websocket.Conn)  {
	for i, stock := range stocks {
		err := websocket.Message.Send(ws, common.SendMessage(bson.M{
			"url": "/stkdata",
			"qs": bson.M{
				"obj": stock,
				"field": "ZhangFu,ZuiXinJia,LiuTongAGu,ZhangDie,ZhongWenJianCheng,ShiFouTingPai,RongZiRongQuanBiaoJi," +
					"KaiPanJia,ZuiGaoJia,ZuiDiJia,ChengJiaoLiang,ChengJiaoE",
				"sub": "1",
				"qid": fmt.Sprintf("%d", i),
			},
		}))
		if err != nil {
			logger.Error(err.Error())
		}
	}
}
//websocket处理消息
func stkOnMessage(res string)  {
	stk := new(stkdata)
	json.Unmarshal([]byte(res), stk)
	if stk.Err != 0 {
		logger.Error("dzh error")
		return
	}
	saveStkData(stk.Data.RepDataStkData)
	//logger.Info("save")
}

type stkdata struct {
	Qid string
	Err int
	Counter int
	Data *data
}

type data struct {
	Id int
	ObjCount int
	RepDataStkData []*repDataStkData
}

type repDataStkData struct {
	Obj string
	ZhongWenJianCheng string
	ShiFouTingPai int
	RongZiRongQuanBiaoJi int
	XuHao int
	ZhangFu float64
	ZuiXinJia float64
	LiuTongAGu float64
	ZhangDie float64
	KaiPanJia float64
	ZuiGaoJia float64
	ZuiDiJia float64
	ChengJiaoLiang float64
	ChengJiaoE float64
}
//保存大行情数据
func saveStkData(stkdatas[]*repDataStkData)  {
	for _, v := range stkdatas {
		//保存股票最新价
		go func(stkdata *repDataStkData) {
			//defer wg.Done()
			eCode := stkdata.Obj
			zuiXinJia := stkdata.ZuiXinJia
			if eCode != "" {
				redisService.SaveStockPrice(zuiXinJia, eCode)
			}
		}(v)
		//保存过涨幅
		go func(stkdata *repDataStkData) {
			zhangFu := stkdata.ZhangFu
			eCode := stkdata.Obj
			if eCode != "" {
				redisService.SaveZhangFu(zhangFu, eCode)
			}
		}(v)
		//保存股票大行情数据
		go func(stkdata *repDataStkData) {
			stkdataMap := make(map[string]interface{})
			str, _:= json.Marshal(stkdata)
			json.Unmarshal(str, &stkdataMap)
			if stkdata.Obj != "" {
				redisService.SaveStkData(stkdata.Obj, stkdataMap)
			}
		}(v)
		//个股提醒
		go func(stkdata *repDataStkData) {
			eCode := stkdata.Obj
			name := stkdata.ZhongWenJianCheng
			nowPrice := stkdata.ZuiXinJia
			percent := stkdata.ZhangFu
			//if eCode == "SH600000" {
			//	logger.Info(fmt.Sprintf("%s %s %f %f", eCode, name, nowPrice, percent))
			//	nowPrice = 10
			//	percent = 1
			//}
			if name == "" || eCode == "" || nowPrice == 0 || percent == 0 {
				return
			}
			limit := redisService.GetRemindLimitValue(eCode)
			low := limit[0]
			var createFlag bool = false
			if low != ""  {
				lowF, _ := strconv.ParseFloat(low, 64)
				if lowF > nowPrice {
					createFlag = true
				}
			}
			high := limit[1]
			if high != ""  {
				highF, _ := strconv.ParseFloat(high, 64)
				if highF < nowPrice {
					createFlag = true
				}
			}
			lowPercent := limit[2]
			if lowPercent != ""  {
				lowPercentF, _ := strconv.ParseFloat(lowPercent, 64)
				if lowPercentF > percent {
					createFlag = true
				}
			}
			highPercent := limit[3]
			if highPercent != ""  {
				highPercentF, _ := strconv.ParseFloat(highPercent, 64)
				if highPercentF < percent {
					createFlag = true
				}
			}
			if createFlag {
				logger.Info(name, eCode, nowPrice, percent)
				dataMap := map[string]interface{}{
					"name": name,
					"eCode": eCode,
					"nowPrice": nowPrice,
					"percent": percent,
				}
				createJob("remindStock", dataMap)
			}
		}(v)
		//创建停牌任务
		go func(stkdata *repDataStkData) {
			if stkdata.Obj != "" && stkdata.ShiFouTingPai == 1 {
				createJob("tingPai", map[string]interface{}{"eCode": stkdata.Obj})
			}

		}(v)
	}
}

func ping(ws *websocket.Conn)  {
	w := bufio.NewWriter(ws)
	w.Write([]byte("ping"))
	w.Flush()
}
//创建个股提醒任务
func createJob(jobName string, dataMap map[string]interface{})  {
	dataJSON, err := json.Marshal(dataMap)
	if err != nil {
		logger.Error("json解析错误")
		return
	}
	form := url.Values{
		"data": []string{string(dataJSON)},
		"job": []string{jobName},
	}
	res, err := http.Post(fmt.Sprintf("%s/createJob", serverUrl), "application/x-www-form-urlencoded", strings.NewReader(form.Encode()))
	defer res.Body.Close()
	if err != nil {
		logger.Error(err.Error())
	}

}